package com.example.zz.example.pattern.hook;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author: zhuozhang6
 * @date: 2022/1/12
 * @email: zhuozhang6@iflytek.com
 * @Description: hook技术，反射、动态代理的应用，应用点击事件hook
 * https://zhuanlan.zhihu.com/p/86534217
 */
public class HookTestMain {

    private static class MyView {
        private MyTestView myTestView;
        private ProcInterface procInterface;
        private ProcInterface procInterface1;

        private static class MyTestView {
            public void test() {
                System.out.println("啊啊啊");
            }
        }

        public interface ProcInterface {
            public void test();
        }

    }


    private static class Other extends MyView.MyTestView {
        @Override
        public void test() {
            System.out.println("BBBBB");
//            super.test();
        }
    }

    public static void main(String[] args) {
        MyView myView = new MyView();
        try {
            Field myTestView = MyView.class.getDeclaredField("myTestView");
            myTestView.setAccessible(true);
            Other other = new Other();
            myTestView.set(myView, other);
            System.out.println("代理后：");
            myView.myTestView.test();

            Field other2 = MyView.class.getDeclaredField("procInterface");
            other2.setAccessible(true);
            other2.set(myView, new MyView.ProcInterface() {
                @Override
                public void test() {
                    System.out.println("CCC");
                }
            });
            myView.procInterface.test();

            Field other3 = MyView.class.getDeclaredField("procInterface1");
            other3.setAccessible(true);
            MyView.ProcInterface procInterface = (MyView.ProcInterface) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                    new Class[]{MyView.ProcInterface.class},
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("这是代理的对象呀：" + method.getName());
                            return null;
                        }
                    });
            other3.set(myView, procInterface);
            myView.procInterface1.test();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
